#ifndef TOTALTEST_H
#define TOTALTEST_H

#include <QObject>
#include <QString>

namespace TotalTest {
struct TestCreatorBase {
    virtual ~TestCreatorBase() = default;
    virtual QObject *createTest() = 0;
    virtual QString name() = 0;
};

template <typename T> struct TestCreator : TestCreatorBase {
    QObject *createTest() override { return new T; }
    QString name() override { return QString::fromLatin1(T::staticMetaObject.className()); }
};

void addTest(TestCreatorBase *creator);
void addQuickTest(const QString &str);
int execTestTask(int argc, char *argv[], int flags);

template <class T> class Test {
public:
    explicit Test(const QString &name) {
        auto test = new TestCreator<T>();
        TotalTest::addTest(test);
    }
};

class QuickTest {
public:
    explicit QuickTest(const QString &name) { addQuickTest(name); }
};

} // namespace TotalTest


#define DECLARE_TEST(className) static TotalTest::Test<className> t(#className);
#define DECLARE_QUICK_TEST(TestTargetName) static TotalTest::QuickTest t2(#TestTargetName);

#define TEST_MAIN                                                                                                      \
    int main(int argc, char *argv[]) { return TotalTest::execTestTask(argc, argv, 0); }

#define TEST_WIDGET_MAIN                                                                                               \
    int main(int argc, char *argv[]) { return TotalTest::execTestTask(argc, argv, 1); }

#define TEST_GUI_MAIN                                                                                                  \
    int main(int argc, char *argv[]) { return TotalTest::execTestTask(argc, argv, 2); }

#define TEST_CORE_MAIN                                                                                                 \
    int main(int argc, char *argv[]) { return TotalTest::execTestTask(argc, argv, 3); }

#endif // TOTALTEST_H